"""
Live2D 模型验证脚本
检查模型文件完整性和配置正确性
"""

import json
from pathlib import Path
import sys

def check_model_files(model_dir):
    """检查模型文件"""
    print("\n" + "=" * 60)
    print("检查模型文件")
    print("=" * 60)
    
    # 尝试查找不同命名的模型文件
    model_json_files = list(model_dir.glob("*.model3.json"))
    moc3_files = list(model_dir.glob("*.moc3"))
    
    if not model_json_files and not moc3_files:
        print("\n⚠ 当前目录没有模型文件，检查 runtime 子目录...")
        runtime_dir = model_dir / "runtime"
        if runtime_dir.exists():
            model_dir = runtime_dir
            model_json_files = list(model_dir.glob("*.model3.json"))
            moc3_files = list(model_dir.glob("*.moc3"))
            print(f"  ⚠ 模型文件在 runtime 子目录：{runtime_dir}")
    
    print("\n必需文件:")
    
    all_required_exist = True
    
    # 检查 .model3.json 文件
    if model_json_files:
        for model_file in model_json_files:
            size = model_file.stat().st_size
            print(f"  ✓ {model_file.name}")
            print(f"    模型配置文件 ({size:,} bytes)")
    else:
        print(f"  ✗ *.model3.json")
        print(f"    模型配置文件 (缺失)")
        all_required_exist = False
    
    # 检查 .moc3 文件
    if moc3_files:
        for moc_file in moc3_files:
            size = moc_file.stat().st_size
            print(f"  ✓ {moc_file.name}")
            print(f"    模型数据文件 ({size:,} bytes)")
    else:
        print(f"  ✗ *.moc3")
        print(f"    模型数据文件 (缺失)")
        all_required_exist = False
    
    # 检查可选文件
    print("\n可选文件:")
    
    physics_files = list(model_dir.glob("*.physics3.json"))
    if physics_files:
        for physics_file in physics_files:
            size = physics_file.stat().st_size
            print(f"  ✓ {physics_file.name}")
            print(f"    物理效果文件 ({size:,} bytes)")
    else:
        print(f"  - *.physics3.json")
        print(f"    物理效果文件 (未找到)")
    
    # 检查贴图文件
    texture_dirs = [model_dir / "textures", model_dir / "hiyori_free_t08.2048"]
    texture_found = False
    
    for tex_dir in texture_dirs:
        if tex_dir.exists():
            texture_files = list(tex_dir.glob("*.png"))
            if texture_files:
                for texture_file in texture_files:
                    size = texture_file.stat().st_size
                    print(f"  ✓ {texture_file.relative_to(model_dir)}")
                    print(f"    贴图文件 ({size:,} bytes)")
                    texture_found = True
    
    if not texture_found:
        print(f"  - textures/*.png")
        print(f"    贴图文件 (未找到)")
    
    # 检查动作文件
    motion_dir = model_dir / "motion"
    if motion_dir.exists():
        motion_files = list(motion_dir.glob("*.motion3.json"))
        if motion_files:
            print(f"\n动作文件:")
            print(f"  ✓ 找到 {len(motion_files)} 个动作文件")
    
    return all_required_exist, model_dir


def check_model_json(model_dir):
    """检查模型 JSON 配置"""
    print("\n" + "=" * 60)
    print("验证模型配置文件")
    print("=" * 60)
    
    # 查找任何 .model3.json 文件
    model_json_files = list(model_dir.glob("*.model3.json"))
    
    if not model_json_files:
        print("✗ 模型配置文件不存在")
        return False
    
    # 使用找到的第一个模型文件
    model_json_path = model_json_files[0]
    print(f"\n使用模型文件: {model_json_path.name}")
    
    try:
        with open(model_json_path, 'r', encoding='utf-8') as f:
            model_data = json.load(f)
        
        print("\n模型信息:")
        print(f"  版本: {model_data.get('Version', 'N/A')}")
        
        # 检查文件引用
        file_references = model_data.get('FileReferences', {})
        
        if 'Moc' in file_references:
            moc_file = model_dir / file_references['Moc']
            exists = "✓" if moc_file.exists() else "✗"
            print(f"  {exists} 模型文件: {file_references['Moc']}")
        
        if 'Textures' in file_references:
            print(f"  贴图数量: {len(file_references['Textures'])}")
            for i, texture in enumerate(file_references['Textures']):
                texture_path = model_dir / texture
                exists = "✓" if texture_path.exists() else "✗"
                print(f"    {exists} {texture}")
        
        if 'Physics' in file_references:
            physics_file = model_dir / file_references['Physics']
            exists = "✓" if physics_file.exists() else "✗"
            print(f"  {exists} 物理文件: {file_references['Physics']}")
        
        # 检查动作和表情
        if 'Motions' in file_references:
            motions = file_references['Motions']
            motion_count = sum(len(m) for m in motions.values() if isinstance(m, list))
            print(f"  动作数量: {motion_count}")
            for category, motion_list in motions.items():
                if isinstance(motion_list, list):
                    print(f"    - {category}: {len(motion_list)} 个")
        
        if 'Expressions' in model_data:
            print(f"  表情数量: {len(model_data['Expressions'])}")
        
        # 检查口型同步参数
        groups = model_data.get('Groups', [])
        lipsync_found = False
        for group in groups:
            if group.get('Name') == 'LipSync':
                lipsync_found = True
                print(f"\n  ✓ 支持口型同步")
                print(f"    参数: {', '.join(group.get('Ids', []))}")
                break
        
        if not lipsync_found:
            print(f"\n  ⚠ 未找到口型同步配置")
        
        print("\n✓ 模型配置文件有效")
        return True
        
    except json.JSONDecodeError as e:
        print(f"✗ JSON 解析错误: {e}")
        return False
    except Exception as e:
        print(f"✗ 验证失败: {e}")
        return False


def check_config_file():
    """检查系统配置文件"""
    print("\n" + "=" * 60)
    print("检查系统配置")
    print("=" * 60)
    
    config_path = Path("config/config.yaml")
    
    if not config_path.exists():
        print("✗ 配置文件不存在: config/config.yaml")
        return False
    
    try:
        import yaml
        
        with open(config_path, 'r', encoding='utf-8') as f:
            config = yaml.safe_load(f)
        
        live2d_config = config.get('live2d', {})
        model_path = live2d_config.get('model_path', '')
        
        print(f"\n配置的模型路径: {model_path}")
        
        # 验证路径是否存在
        if model_path:
            full_path = Path(model_path)
            if full_path.exists():
                print(f"✓ 模型路径有效")
            else:
                print(f"⚠ 模型路径不存在，但可能在运行时创建")
        
        # 显示其他配置
        print(f"\n其他 Live2D 配置:")
        print(f"  窗口大小: {live2d_config.get('window_size', 'N/A')}")
        print(f"  帧率: {live2d_config.get('fps', 'N/A')}")
        print(f"  背景颜色: {live2d_config.get('background_color', 'N/A')}")
        
        return True
        
    except ImportError:
        print("✗ 需要安装 pyyaml: pip install pyyaml")
        return False
    except Exception as e:
        print(f"✗ 配置文件验证失败: {e}")
        return False


def main():
    """主函数"""
    print("=" * 60)
    print("Live2D 模型验证工具")
    print("=" * 60)
    
    project_root = Path(__file__).parent
    model_dir = project_root / "models" / "hiyori"
    
    print(f"\n模型目录: {model_dir}")
    
    if not model_dir.exists():
        print("\n✗ 模型目录不存在")
        print("\n请先下载模型:")
        print("  1. 运行: python download_live2d_model.py")
        print("  2. 或参考: LIVE2D_DOWNLOAD_GUIDE.md 手动下载")
        return False
    
    # 执行各项检查
    results = []
    
    files_result, actual_model_dir = check_model_files(model_dir)
    results.append(("模型文件", files_result))
    results.append(("模型配置", check_model_json(actual_model_dir)))
    results.append(("系统配置", check_config_file()))
    
    # 输出总结
    print("\n" + "=" * 60)
    print("验证结果总结")
    print("=" * 60)
    
    for name, result in results:
        status = "✓ 通过" if result else "✗ 失败"
        print(f"{name}: {status}")
    
    all_passed = all(r[1] for r in results)
    
    if all_passed:
        print("\n✓ 所有检查通过！")
        print("\n可以启动完整系统:")
        print("  python main.py")
    else:
        print("\n⚠ 部分检查未通过")
        print("\n建议:")
        print("  1. 检查模型文件是否完整")
        print("  2. 参考 LIVE2D_DOWNLOAD_GUIDE.md 重新下载")
        print("  3. 或先使用简化模式: python demo_without_live2d.py --auto")
    
    return all_passed


if __name__ == "__main__":
    success = main()
    sys.exit(0 if success else 1)
